UE5 Quest System
This page is part of the documentaiton for my UE5 Quest System

Save & Load System

UE5 Quest System Version: 2.0

    How Saving & Loading works ...

    Saving and loading of quest related data occurs for you automatically through the AC_QuestSystem_PlayerState as long as the option SavePlayerQuests? is set to true on the AC_QuestSystem_PlayerController you attached to your player controller during installation.

    saveQuestSystem - This is the function that is called when it is time to save quests.
    loadQuestSystem - This is the function that is called when it is time to load quests.

    New Player Detection

    There is an empty helper function inside AC_QuestSystem_PlayerState called runNewPlayerEvents that you can use if there is some kind of specific functionality you want to initialize when a new player (one that did not have any save game) is detected by the quest system.

    Player Verification

    The loading side of the system offers the option to validate that the player ID and game ID match the one trying to load the save game file. This feature can be used to prevent sharing of save files. By default this check is enabled, and to disable it, set the validateSaveOwner boolean in the AC_QuestSystem_PlayerState to false.

    Multiplayer Player Identification

    Player identification is mostly used for multiplayer, and you can learn all about it from that chapter of the documentation.

    Game Identification

    If you are manually setting up the quest system (see installation section) you can supply a game identifier. This can be helpful for single player games where there are multiple save game slots. By default if you let the system automatically handle setup the game identifier will be set to "sandbox". This default string can be changed on the Begin Play event of the AC_QuestSystem_PlayerController.

    Save Game Slot Name

    The combination of both the game identifier and player id is used to create the save game slot name. The continueIfSaving macro is where the filename is generated. The string is formatted as follows: DQS(separator)$GameID(separator)players(separator)$PlayerID. In this string $GameID and $PlayerID are the dynamic values. (separator) which is "/" by default can be changed by modifying the SaveFileSystemSeparator enum. The possible values are forward slash (/), underscore (_), hyphen(-), and period(.). So for example if your game id is sandbox and your player id is 4 your save game file name (using the default forward slash separator) will be DQS/sandbox/players/4.sav.

    Save Game Object & Variables

    The save game object SGO_Quest_Player used by the quest system can be found in the Blueprints/Variables/SaveGames folder. In the previous version we had multiple files for saving different things. In this version everything is combined into this one save game object. Here are the variables:

    questStates - This is where all the players current quest states are saved. This is a map variable, consisting of the questRowName as the key, and the enumeration QuestState as the value.
    gameID - Used to verify that the current gameID matches. The game ID is saved when the save game is first created. How and where the game identifier comes from is mentioned above.
    playerID - Used to verify that the current playerID matches. The player ID is saved when the save game is first created. The original source of the player id is described above, and in the multiplayer chapter of this documentation.
    inProgressObjectivesComplete - This array of Objective Identifiers keeps track of the objectives that are currently completed by any quests currently in the In Progress state. See below for details about objective identifiers.
    TrackingQuests - The quests currently being tracked by the player. A tracked quest is one that is shown on the HUD (right side of the screen by default).
    objectiveCounters - If an objective uses the Count Target Data this map is used to keep track of the current counts. The key is an objective identifier and the value is the current count. See below for details about objective identifiers.
    questTimersSecondsRemaining - This map is where we keep track of the seconds remaining when we are using a quest timer for a quest that is currently in progress. The key is an objective identifier, and the value is a float for the seconds remaining in the timer. See below for details about objective identifiers.

    What is an objective identifier?

    In a few of these we mention the use of Objective Identifiers. An objective identifier is formed by combining the QuestRowName, a period, and the ObjectiveIndex all together.

    For example an objective identifier for the 3rd objective of the quest main-story would look like: main-story.2. Remember our objective are stored in an array so our indexes start at 0. Index 0 is the first objective, Index 1 is the 2nd objective, and index 2 is the third objective.

    In some blueprints, like our AC_QuestSystem_PlayerState you will find a macro to assist with creating our objective identifier.

    Delayed Saving

    Internally we will use a short retriggerable delay to initialize the saving process for most of our calls. This is used to prevent multiple back to back calls to the save handler.

    For example when we destroy the last target for our objective, and our objective is the last to complete the quest, which in turn will trigger the quest state to change to Ready to Turn In.

    This is 3 different actions being performed all at nearly the same time: a count increment, an objective completed, and a quest state change.

    By themselves each action can initiate a save. Since we use a retriggerable delay this will make sure all the updates are posted to the associated variables, and the last one through is the one which actually initiates the saving handler process.

    The delayedSavePlayer event is the one that is called, if you would like to see where it is used right click on this event and select Find References.

    Manually Saving

    If you would like to manually save, the easiest way would be to disable the execution pin on the delayedSavePlayer event, since internally all save attempts are passed through this event. You would then need to call saveQuestSystem whenever you want to Save the state of the quest system for the player.

    This documentation and asset version are new. If you encounter any bugs or if anything doesn't make sense, please let me know.